package com.sunwhite.herostore.common;

import com.google.protobuf.GeneratedMessageV3;
import com.sunwhite.herostore.cmdhandler.CmdHandler;
import com.sunwhite.herostore.cmdhandler.CmdHandlerFactory;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainThreadProcessor {
    /**
     * 日志对象
     *
     */
    private final static Logger log= LoggerFactory.getLogger(MainThreadProcessor.class);
    /**
     * 单例对象
     */
    private final  static MainThreadProcessor mainThreadProcessor=new MainThreadProcessor();

    /**
     * 私有化默认构造方法
     */
    private MainThreadProcessor(){}

    public static MainThreadProcessor getInstance(){
        return mainThreadProcessor;
    }

    /**
     * 创建一个单线程线程池
     */
    private final  ExecutorService es= Executors.newSingleThreadExecutor((newRunnable)->{
        Thread thread = new Thread(newRunnable);
        thread.setName("MainThreadProcessor");
        return thread;
    });

    /***
     * 主线执行线程操作
     * @param runnable 需要执行的线城
     */
    public void process(Runnable runnable){
        if (runnable==null){
            return;
        }
        es.submit(runnable);
    }


    /**
     * 处理客户端消息
     * @param ctx 消息通道
     * @param msg 消息对象
     */
    public  void process(ChannelHandlerContext ctx, GeneratedMessageV3 msg){
        if (null==ctx||null==msg){
            return;
        }
        //获取消息类
        Class<? extends GeneratedMessageV3> msgClass = msg.getClass();

        log.info("收到客户消息：msgClazz={},处理线程={}",msgClass,Thread.currentThread().getName());

        /**
         * 将处理内容交给单线程线程池处理
         */
        es.submit(()->{
            CmdHandler<? extends GeneratedMessageV3> cmdHandler = CmdHandlerFactory.create(msgClass);
            if (cmdHandler==null){
                log.error("未找到响应的消息处理器，msgClass={}",msgClass);
                return;
            }
            //这里一定要捕捉异常避免线程中断
            try {
                cmdHandler.handle(ctx,cast(msg));
            } catch (Exception e) {

                log.error(e.getMessage(),e);
            }
        });
    }

    /**
     * 转型消息对象
     * @param msg
     * @param <T>
     * @return
     */
    private <T extends GeneratedMessageV3> T cast(Object msg) {
        if (null==msg||!(msg instanceof GeneratedMessageV3)){
            return null;
        }
        return (T) msg;
    }
}
